package com.dong.ch03_stack_queue;


import sun.swing.plaf.synth.DefaultSynthStyle;

import java.util.Arrays;

/**
 * 循环队列
 */
public class QueueCircle<E> implements Queue<E> {
    public static final int INIT_SIZE=8;
    private int front;
    private int tail;
    private E[] data;
    private int size;

    public QueueCircle(int capacity) {
        if (capacity<=0) {
            capacity=INIT_SIZE+1;
        }
        data= (E[]) new Object[capacity+1];
        front=0;
        tail=0;
        size=0;
    }
    public QueueCircle() {
        this(INIT_SIZE);
    }
    @Override
    public int getSize() {
        return size;
    }

    /**
     * 用于对size的维护  方便统一取消对size的操作
     * @param offset
     */
    private void offsetSize(int offset) {
        this.size+=offset;
    }
    public int getCapacity(){
        return data.length-1;
    }

    @Override
    public boolean isEmpty() {
        return front==tail;
    }

    @Override
    public void enqueue(E e) {
        //满了
        if((tail+1)%data.length==front) {
            resize(true);
        }
        data[tail]=e;
        tail=(tail+data.length+1)%data.length;
        offsetSize(1);
    }

    /**
     *
     * @param doubleSize   true: 扩容,  false : 缩容
     */
    private void resize(boolean doubleSize) {
        System.out.println("------------> 进行容量变更");
        int targetSize = doubleSize?data.length*2-1:data.length/2+1;
        E[] newData= (E[]) new Object[targetSize];
        int newTail =getSize();
        int newFront=0;
        for (int i = 0; i < getSize(); i++) {
            newData[i]=data[(front+i)%data.length];
        }
        data=newData;
        front=newFront;
        tail=newTail;

    }

    @Override
    public E dequeue() {
        if(isEmpty()) {
            throw new RuntimeException("queue is empty now!");
        }
        if(getSize()*4<data.length) {
            resize(false);
        }
        E current = data[front];
        front=(front+data.length+1)%data.length;
        offsetSize(-1);
        return current;
    }

    @Override
    public E getFront() {
        if(isEmpty()) {
            throw new RuntimeException("queue is empty now!");
        }
        E current = data[front];
        return current;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer(getSize()*4);
        for (int i = 0; i < size-1; i++) {
            sb.append(data[(i+front)%data.length]).append(",");
        }
        sb.append(data[(getSize()-1+front)%data.length]);
        return "QueueCircle{" +
         //       "head=" + front +
                ", data=" + sb.toString() +
         //       ", tail=" + tail +
     //           ", size=" + size +
                '}';
    }

    public static void main(String[] args) {
        Queue<Integer> queue = new QueueCircle<>(2);
        for (int i = 0; i < 10; i++) {
            queue.enqueue(i);
            System.out.println(queue);
            if(i%3==2) {
                Integer dequeue = queue.dequeue();
                System.out.println(queue);
            }
        }
    }
}
